package com.lap.auth.application.authorization.assembler;

import com.lap.auth.application.authorization.dto.ApiDto;
import com.lap.auth.application.authorization.dto.DataScopeDto;
import com.lap.auth.application.authorization.dto.MenuViewDto;
import com.lap.auth.application.role.dto.RoleDataScopeDto;
import com.lap.auth.domain.api.Api;
import com.lap.auth.domain.menu.Menu;
import com.lap.framework.tools.BooleanStrategy;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper(componentModel = "spring")
public interface AuthorAssembler {
  Integer ZERO = 0;

  ApiDto toDto(Api api);

  List<ApiDto> toDtoList(List<Api> apiList);

  DataScopeDto toDataScopeDto(RoleDataScopeDto dto);

  @Mapping(target = "meta.isHide", source = "meta.hide")
  @Mapping(target = "meta.isKeepAlive", source = "meta.keepAlive")
  @Mapping(target = "meta.isAffix", source = "meta.affix")
  @Mapping(target = "meta.isIframe", source = "meta.iframe")
  @Mapping(target = "children", ignore = true)
  MenuViewDto toMenuDto(Menu menu);

  List<MenuViewDto> toMenuDtoList(List<Menu> list);

  default boolean intToBool(Integer value) {
    return BooleanStrategy.toBoolean(value);
  }

  default List<MenuViewDto> convertToTree(List<MenuViewDto> allList) {
    List<MenuViewDto> roots = new ArrayList<>();
    Map<Integer, MenuViewDto> nodeMap = new HashMap<>();
    for (MenuViewDto dto : allList) {
      dto.setChildren(new ArrayList<>());
      nodeMap.put(dto.getId(), dto);
    }

    for (MenuViewDto dto : allList) {
      if (Objects.equals(dto.getPid(), ZERO)) {
        roots.add(dto);
      } else {
        MenuViewDto parent = nodeMap.get(dto.getPid());
        if (parent != null) {
          parent.getChildren().add(dto);
        }
      }
    }

    for (MenuViewDto dto : nodeMap.values()) {
      dto.getChildren().sort(Comparator.comparing(MenuViewDto::getSortOrder));
    }
    roots.sort(Comparator.comparing(MenuViewDto::getSortOrder));
    return roots;
  }
}
